package elephant.rpc.network.netty.codec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import elephant.rpc.server.RPCServer;
import elephant.rpc.server.core.PerformMonitor;
import elephant.rpc.server.message.RPCMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;


@Sharable
public class FastJsonMessageEncoder extends MessageToByteEncoder<RPCMessage> {
	//
	private static Logger logger=LoggerFactory.getLogger(FastJsonMessageEncoder.class);
	//
	PerformMonitor performMonitor;
	//
	public FastJsonMessageEncoder(PerformMonitor performMonitor) {
		this.performMonitor=performMonitor;
	}
	
	@Override
	protected void encode(
			ChannelHandlerContext ctx, 
			RPCMessage msg,
			ByteBuf out) throws Exception {
		try {
			encode0(ctx, msg, out);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			RPCMessage rsp=RPCMessage.createRspMsg(msg.id,null,0,e.getMessage(),new RuntimeException(e));
			encode0(ctx, rsp, out);
		}
	}
	
	protected void encode0(
			ChannelHandlerContext ctx, 
			RPCMessage msg,
			ByteBuf out) throws Exception {
		long startTime=System.currentTimeMillis();
    	byte compressBytes[]=JSON.toJSONBytes(msg,SerializerFeature.WriteClassName);
    	int dataLength=compressBytes.length;
    	
    	if(dataLength>RPCServer.maxMsgLength){
			throw new IllegalArgumentException("message too long" + dataLength
					+ "/" + RPCServer.maxMsgLength);
		}
		out.writeInt(dataLength);
		out.writeBytes(compressBytes);
		performMonitor.addTrafficOut(dataLength);
		//
		long endTime=System.currentTimeMillis();
		if(logger.isDebugEnabled()){
    		logger.debug("encode using {}ms dataLength:{}",
    				(endTime-startTime),
    				dataLength);
    	}
	}
}
